from abc import ABCMeta, abstractmethod

class Node(object):
    
    __metaclass__ = ABCMeta
              
    def __init__(self):
        self.__components = []
        self.__parent = None
              
    def add(self, component):
        self.components.append(component)
        component.parent = self
        component.on_added()
        return self
    
    def remove(self, component):
        self.components.remove(component)
        component.parent = None
        component.on_removed()
        
    def destroy(self):
        self.parent.remove(self)
    
    def on_added(self): 
        pass
    
    def on_removed(self):
        pass
    
    @property
    def components(self):
        return self.__components
    
    @property
    def parent(self):
        return self.__parent
    
    @parent.setter
    def parent(self, value):
        self.__parent = value


class Component(Node):
    
    __metaclass__ = ABCMeta
    
    def __init__(self): 
        Node.__init__(self)
        self.__x = 0
        self.__y = 0  
            
    def on_update(self):
        self.update()
        for component in self.components:
            component.on_update()
            
    def on_draw(self):
        self.draw()
        for component in self.components:
            component.on_draw()

    @abstractmethod
    def draw(self): pass

    @abstractmethod
    def update(self): pass


    @property
    def gx(self):
        return self.__x + self.parent.gx
    
    @property
    def gy(self):
        return self.__y + self.parent.gy
   
    @property
    def x(self):
        return self.__x
    
    @x.setter
    def x(self, value):
        self.__x = value
    
    @property
    def y(self):
        return self.__y

    @y.setter
    def y(self, value):
        self.__y = value